package cn.ruanyun.backInterface.modules.business.storeIncome.serviceimpl;

import cn.ruanyun.backInterface.common.enums.BooleanTypeEnum;
import cn.ruanyun.backInterface.modules.base.service.mybatis.IUserRoleService;
import cn.ruanyun.backInterface.modules.base.service.mybatis.IUserService;
import cn.ruanyun.backInterface.modules.business.order.service.IOrderService;
import cn.ruanyun.backInterface.modules.business.profitDetail.pojo.ProfitDetail;
import cn.ruanyun.backInterface.modules.business.profitDetail.service.IProfitDetailService;
import cn.ruanyun.backInterface.modules.business.storeIncome.mapper.StoreIncomeMapper;
import cn.ruanyun.backInterface.modules.business.storeIncome.pojo.StoreIncome;
import cn.ruanyun.backInterface.modules.business.storeIncome.service.IStoreIncomeService;
import cn.ruanyun.backInterface.modules.business.storeIncome.vo.StoreIncomeCountVo;
import cn.ruanyun.backInterface.modules.business.storeIncome.vo.StoreIncomeVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import cn.ruanyun.backInterface.common.utils.ToolUtil;
import cn.ruanyun.backInterface.common.utils.SecurityUtil;
import cn.ruanyun.backInterface.common.utils.ThreadPoolUtil;


/**
 * 店铺收入接口实现
 * @author z
 */
@Slf4j
@Service
@Transactional
public class IStoreIncomeServiceImpl extends ServiceImpl<StoreIncomeMapper, StoreIncome> implements IStoreIncomeService {


       @Autowired
       private SecurityUtil securityUtil;

       @Autowired
       private IUserService userService;

       @Autowired
       private IOrderService orderService;

       @Autowired
       private IUserRoleService userRoleService;

       @Autowired
       private IProfitDetailService profitDetailService;

       @Override
       public void insertOrderUpdateStoreIncome(StoreIncome storeIncome) {

           if (ToolUtil.isEmpty(storeIncome.getCreateBy())) {

                       storeIncome.setCreateBy(securityUtil.getCurrUser().getId());
                   }else {

                       storeIncome.setUpdateBy(securityUtil.getCurrUser().getId());
                   }


                   Mono.fromCompletionStage(CompletableFuture.runAsync(() -> this.saveOrUpdate(storeIncome)))
                           .publishOn(Schedulers.fromExecutor(ThreadPoolUtil.getPool()))
                           .toFuture().join();
       }

      @Override
      public void removeStoreIncome(String ids) {

          CompletableFuture.runAsync(() -> this.removeByIds(ToolUtil.splitterStr(ids)));
      }

    @Override
    public List<StoreIncomeVo> getStoreIncomeList() {

           return Optional.ofNullable(ToolUtil.setListToNul(this.list(Wrappers.<StoreIncome>lambdaQuery()
           .eq(StoreIncome::getCreateBy, securityUtil.getCurrUser().getId())
           .orderByDesc(StoreIncome::getCreateTime))))
           .map(storeIncomes -> storeIncomes.parallelStream().flatMap(storeIncome -> {

               StoreIncomeVo storeIncomeVo = new StoreIncomeVo();

               //订单信息
               Optional.ofNullable(orderService.getById(storeIncome.getOrderId())).ifPresent(order -> {

                   ToolUtil.copyProperties(order, storeIncomeVo);

                   storeIncomeVo.setBuyTime(order.getCreateTime())
                           .setPayType(order.getPayTypeEnum());

                   Optional.ofNullable(userService.getById(order.getCreateBy())).ifPresent(user -> {

                       storeIncomeVo.setBuyerName(user.getNickName())
                               .setBuyerMobile(user.getMobile());
                   });
               });

               //收入信息
               ToolUtil.copyProperties(storeIncome, storeIncomeVo);
               storeIncomeVo.setIncomeTime(storeIncome.getCreateTime());

               return Stream.of(storeIncomeVo);
           }).collect(Collectors.toList()))
           .orElse(null);

    }

    @Override
    public StoreIncomeCountVo getStoreIncomeCount() {

           StoreIncomeCountVo storeIncomeCountVo = new StoreIncomeCountVo();

           String storeId = securityUtil.getCurrUser().getId();;

           //如果是平台，看全部
        String roleIdsByUserId = userRoleService.getRoleIdsByUserId(storeId);

        if ("496138616573952".equals(roleIdsByUserId)){

            List<ProfitDetail> list = profitDetailService.list(Wrappers.<ProfitDetail>lambdaQuery()
                    .isNull(ProfitDetail::getCreateBy)
                    .eq(ProfitDetail::getProfitStatus, BooleanTypeEnum.YES)
            );

            return Optional.ofNullable(ToolUtil.setListToNul(list))
                    .map(storeIncomes -> {

                        //日收入
                        BigDecimal dayIncome = storeIncomes.parallelStream().filter(storeIncome ->
                                getDay(storeIncome.getCreateTime()).equals(getDay(new Date())))
                                .map(ProfitDetail::getProfitMoney).reduce(BigDecimal.ZERO, BigDecimal::add);

                        //月收入
                        BigDecimal monthIncome = storeIncomes.parallelStream().filter(storeIncome ->
                                getMonth(storeIncome.getCreateTime()).equals(getMonth(new Date())))
                                .map(ProfitDetail::getProfitMoney).reduce(BigDecimal.ZERO, BigDecimal::add);


                        //年收入
                        BigDecimal yearIncome = storeIncomes.parallelStream().filter(storeIncome ->
                                getYear(storeIncome.getCreateTime()).equals(getYear(new Date())))
                                .map(ProfitDetail::getProfitMoney).reduce(BigDecimal.ZERO, BigDecimal::add);

                        //总收入
                        BigDecimal totalIncome = storeIncomes.parallelStream().map(ProfitDetail::getProfitMoney)
                                .reduce(BigDecimal.ZERO, BigDecimal::add);

                        storeIncomeCountVo.setDayIncome(dayIncome).setMonthIncome(monthIncome)
                                .setYearIncome(yearIncome).setTotalIncome(totalIncome);

                        return storeIncomeCountVo;

                    }).orElse(storeIncomeCountVo);
        }


        List<StoreIncome> list = this.list(Wrappers.<StoreIncome>lambdaQuery()
                .eq(ToolUtil.isNotEmpty(storeId),StoreIncome::getCreateBy, storeId));

        return Optional.ofNullable(ToolUtil.setListToNul(list))
                   .map(storeIncomes -> {

                       //日收入
                       BigDecimal dayIncome = storeIncomes.parallelStream().filter(storeIncome ->
                               getDay(storeIncome.getCreateTime()).equals(getDay(new Date())))
                               .map(StoreIncome::getIncomeMoney).reduce(BigDecimal.ZERO, BigDecimal::add);

                       //月收入
                       BigDecimal monthIncome = storeIncomes.parallelStream().filter(storeIncome ->
                               getMonth(storeIncome.getCreateTime()).equals(getMonth(new Date())))
                               .map(StoreIncome::getIncomeMoney).reduce(BigDecimal.ZERO, BigDecimal::add);


                       //年收入
                       BigDecimal yearIncome = storeIncomes.parallelStream().filter(storeIncome ->
                               getYear(storeIncome.getCreateTime()).equals(getYear(new Date())))
                               .map(StoreIncome::getIncomeMoney).reduce(BigDecimal.ZERO, BigDecimal::add);

                       //总收入
                       BigDecimal totalIncome = storeIncomes.parallelStream().map(StoreIncome::getIncomeMoney)
                               .reduce(BigDecimal.ZERO, BigDecimal::add);

                       storeIncomeCountVo.setDayIncome(dayIncome).setMonthIncome(monthIncome)
                               .setYearIncome(yearIncome).setTotalIncome(totalIncome);

                       return storeIncomeCountVo;

                   }).orElse(storeIncomeCountVo);
    }


    /**
     * 獲取当前天
     * @param date  date
     * @return Integer
     */
    public Integer getDay(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE);
    }


    /**
     * 獲取当前月
     * @param date date
     * @return Integer
     */
    public Integer getMonth(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

    /**
     * 獲取当前年
     * @param date date
     * @return Integer
     */
    public Integer getYear(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }


    @Override
    public BigDecimal getStoreIncomeByOrderId(String storeId, String orderId) {

         return Optional.ofNullable(this.getOne(Wrappers.<StoreIncome>lambdaQuery()
         .eq(StoreIncome::getOrderId, orderId)
         .eq(StoreIncome::getCreateBy, storeId)))
         .map(StoreIncome::getIncomeMoney)
         .orElse(new BigDecimal(0));
    }
}